#define IWL49_NUM_QUEUES       16
 #define IWL49_NUM_AMPDU_QUEUES 8
 
-#define IWL_TX_DMA_MASK        (DMA_BIT_MASK(36) & ~0x3)
-#define IWL_NUM_OF_TBS         20
-
-static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
-{
-       return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
-}
-/**
- * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
- *
- * This structure contains dma address and length of transmission address
- *
- * @lo: low [31:0] portion of the dma address of TX buffer
- *     every even is unaligned on 16 bit boundary
- * @hi_n_len 0-3 [35:32] portion of dma
- *          4-16 length of the tx buffer
- */
-struct iwl_tfd_tb {
-       __le32 lo;
-       __le16 hi_n_len;
-} __attribute__((packed));
-
-/**
- * struct iwl_tfd
- *
- * Transmit Frame Descriptor (TFD)
- *
- * @ __reserved1[3] reserved
- * @ num_tbs 0-5 number of active tbs
- *          6-7 padding (not used)
- * @ tbs[20]   transmit frame buffer descriptors
- * @ __pad     padding
- *
- * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
- * Both driver and device share these circular buffers, each of which must be
- * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
- *
- * Driver must indicate the physical address of the base of each
- * circular buffer via the FH_MEM_CBBC_QUEUE registers.
- *
- * Each TFD contains pointer/size information for up to 20 data buffers
- * in host DRAM.  These buffers collectively contain the (one) frame described
- * by the TFD.  Each buffer must be a single contiguous block of memory within
- * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
- * of (4K - 4).  The concatenates all of a TFD's buffers into a single
- * Tx frame, up to 8 KBytes in size.
- *
- * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
- *
- * Bit fields in the control dword (val0):
- */
-struct iwl_tfd {
-       u8 __reserved1[3];
-       u8 num_tbs;
-       struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
-       __le32 __pad;
-} __attribute__ ((packed));
-
 
 /**
  * struct iwl4965_schedq_bc_tbl
  * padding puts each byte count table on a 1024-byte boundary;
  * 4965 assumes tables are separated by 1024 bytes.
  */
-struct iwl4965_schedq_bc_tbl {
+struct iwl4965_scd_bc_tbl {
        __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
        u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
 } __attribute__ ((packed));
 
-
-/**
- * struct iwl4965_shared - handshake area for Tx and Rx
- *
- * For convenience in allocating memory, this structure combines 2 areas of
- * DRAM which must be shared between driver and 4965.  These do not need to
- * be combined, if better allocation would result from keeping them separate:
- *
- * 1)  The Tx byte count tables occupy 1024 bytes each (16 KBytes total for
- *     16 queues).  Driver uses SCD_DRAM_BASE_ADDR to tell 4965 where to find
- *     the first of these tables.  4965 assumes tables are 1024 bytes apart.
- *
- * 2)  The Rx status (val0 and val1) occupies only 8 bytes.  Driver uses
- *     FH_RSCSR_CHNL0_STTS_WPTR_REG to tell 4965 where to find this area.
- *     Driver reads val0 to determine the latest Receive Buffer Descriptor (RBD)
- *     that has been filled by the 4965.
- *
- * Bit fields val0:
- * 31-12:  Not used
- * 11- 0:  Index of last filled Rx buffer descriptor (4965 writes, driver reads)
- *
- * Bit fields val1:
- * 31- 0:  Not used
- */
-struct iwl4965_shared {
-       struct iwl4965_schedq_bc_tbl queues_bc_tbls[IWL49_NUM_QUEUES];
-} __attribute__ ((packed));
-
-#endif /* __iwl4965_4965_hw_h__ */
+#endif /* !__iwl_4965_hw_h__ */
 
 
        /* Tel 4965 where to find Tx byte count tables */
        iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
-               (priv->shared_phys +
-                offsetof(struct iwl4965_shared, queues_bc_tbls)) >> 10);
+                       priv->scd_bc_tbls.dma >> 10);
 
        /* Disable chain mode for all queues */
        iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
        }
 
        priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
+       priv->hw_params.scd_bc_tbls_size =
+                       IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl);
        priv->hw_params.max_stations = IWL4965_STATION_COUNT;
        priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
        priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
 }
 #endif
 
-static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
-{
-       priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
-                                       sizeof(struct iwl4965_shared),
-                                       &priv->shared_phys);
-       if (!priv->shared_virt)
-               return -ENOMEM;
-
-       memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
-
-       return 0;
-}
-
-static void iwl4965_free_shared_mem(struct iwl_priv *priv)
-{
-       if (priv->shared_virt)
-               pci_free_consistent(priv->pci_dev,
-                                   sizeof(struct iwl4965_shared),
-                                   priv->shared_virt,
-                                   priv->shared_phys);
-}
-
 /**
  * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
  */
                                            struct iwl_tx_queue *txq,
                                            u16 byte_cnt)
 {
-       struct iwl4965_shared *shared_data = priv->shared_virt;
+       struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
        int txq_id = txq->q.id;
        int write_ptr = txq->q.write_ptr;
        int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
 
        bc_ent = cpu_to_le16(len & 0xFFF);
        /* Set up byte count within first 256 entries */
-       shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent;
+       scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
 
        /* If within first 64 entries, duplicate at end */
        if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               shared_data->queues_bc_tbls[txq_id].
+               scd_bc_tbl[txq_id].
                        tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 
 
 static struct iwl_lib_ops iwl4965_lib = {
        .set_hw_params = iwl4965_hw_set_hw_params,
-       .alloc_shared_mem = iwl4965_alloc_shared_mem,
-       .free_shared_mem = iwl4965_free_shared_mem,
        .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
        .txq_set_sched = iwl4965_txq_set_sched,
        .txq_agg_enable = iwl4965_txq_agg_enable,
 
  * @tfd_offset  0-12 - tx command byte count
  *            12-16 - station index
  */
-struct iwl5000_schedq_bc_tbl {
+struct iwl5000_scd_bc_tbl {
        __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
 } __attribute__ ((packed));
 
-/**
- * struct iwl5000_shared
- */
-struct iwl5000_shared {
-       struct iwl5000_schedq_bc_tbl queues_bc_tbls[IWL50_NUM_QUEUES];
-} __attribute__ ((packed));
 
 #endif /* __iwl_5000_hw_h__ */
 
 
                iwl_write_targ_mem(priv, a, 0);
 
        iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
-               (priv->shared_phys +
-                offsetof(struct iwl5000_shared, queues_bc_tbls)) >> 10);
+                      priv->scd_bc_tbls.dma >> 10);
        iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
-               IWL50_SCD_QUEUECHAIN_SEL_ALL(
-                       priv->hw_params.max_txq_num));
+               IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
        iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
 
        /* initiate the queues */
        }
 
        priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
+       priv->hw_params.scd_bc_tbls_size =
+                       IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
        priv->hw_params.max_stations = IWL5000_STATION_COUNT;
        priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
        priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
        return 0;
 }
 
-static int iwl5000_alloc_shared_mem(struct iwl_priv *priv)
-{
-       priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
-                                       sizeof(struct iwl5000_shared),
-                                       &priv->shared_phys);
-       if (!priv->shared_virt)
-               return -ENOMEM;
-
-       memset(priv->shared_virt, 0, sizeof(struct iwl5000_shared));
-
-       return 0;
-}
-
-static void iwl5000_free_shared_mem(struct iwl_priv *priv)
-{
-       if (priv->shared_virt)
-               pci_free_consistent(priv->pci_dev,
-                                   sizeof(struct iwl5000_shared),
-                                   priv->shared_virt,
-                                   priv->shared_phys);
-}
-
 /**
  * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
  */
                                            struct iwl_tx_queue *txq,
                                            u16 byte_cnt)
 {
-       struct iwl5000_shared *shared_data = priv->shared_virt;
+       struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
        int write_ptr = txq->q.write_ptr;
        int txq_id = txq->q.id;
        u8 sec_ctl = 0;
 
        bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
 
-       shared_data->queues_bc_tbls[txq_id].tfd_offset[write_ptr] = bc_ent;
+       scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
 
        if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               shared_data->queues_bc_tbls[txq_id].
+               scd_bc_tbl[txq_id].
                        tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 
 static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
                                           struct iwl_tx_queue *txq)
 {
-       struct iwl5000_shared *shared_data = priv->shared_virt;
+       struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
        int txq_id = txq->q.id;
        int read_ptr = txq->q.read_ptr;
        u8 sta_id = 0;
                sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
 
        bc_ent =  cpu_to_le16(1 | (sta_id << 12));
-       shared_data->queues_bc_tbls[txq_id].
-                       tfd_offset[read_ptr] = bc_ent;
+       scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
 
        if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               shared_data->queues_bc_tbls[txq_id].
+               scd_bc_tbl[txq_id].
                        tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] =  bc_ent;
 }
 
 
 static struct iwl_lib_ops iwl5000_lib = {
        .set_hw_params = iwl5000_hw_set_hw_params,
-       .alloc_shared_mem = iwl5000_alloc_shared_mem,
-       .free_shared_mem = iwl5000_free_shared_mem,
        .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
        .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
        .txq_set_sched = iwl5000_txq_set_sched,
 
                priv->cfg->ops->lib->apm_ops.stop(priv);
        else
                priv->cfg->ops->lib->apm_ops.reset(priv);
-       priv->cfg->ops->lib->free_shared_mem(priv);
-
  exit:
        memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
 
        iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 
-       ret = priv->cfg->ops->lib->alloc_shared_mem(priv);
-       if (ret) {
-               IWL_ERROR("Unable to allocate shared memory\n");
-               return ret;
-       }
-
        ret = iwl_hw_nic_init(priv);
        if (ret) {
                IWL_ERROR("Unable to init nic\n");
 
 }
 EXPORT_SYMBOL(iwl_hw_detect);
 
-/* Tell nic where to find the "keep warm" buffer */
-int iwl_kw_init(struct iwl_priv *priv)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       ret = iwl_grab_nic_access(priv);
-       if (ret)
-               goto out;
-
-       iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
-                            priv->kw.dma_addr >> 4);
-       iwl_release_nic_access(priv);
-out:
-       spin_unlock_irqrestore(&priv->lock, flags);
-       return ret;
-}
-
-int iwl_kw_alloc(struct iwl_priv *priv)
-{
-       struct pci_dev *dev = priv->pci_dev;
-       struct iwl_kw *kw = &priv->kw;
-
-       kw->size = IWL_KW_SIZE;
-       kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
-       if (!kw->v_addr)
-               return -ENOMEM;
-
-       return 0;
-}
-
-/**
- * iwl_kw_free - Free the "keep warm" buffer
- */
-void iwl_kw_free(struct iwl_priv *priv)
-{
-       struct pci_dev *dev = priv->pci_dev;
-       struct iwl_kw *kw = &priv->kw;
-
-       if (kw->v_addr) {
-               pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
-               memset(kw, 0, sizeof(*kw));
-       }
-}
-
 int iwl_hw_nic_init(struct iwl_priv *priv)
 {
        unsigned long flags;
 
 struct iwl_lib_ops {
        /* set hw dependent parameters */
        int (*set_hw_params)(struct iwl_priv *priv);
-       /* ucode shared memory */
-       int (*alloc_shared_mem)(struct iwl_priv *priv);
-       void (*free_shared_mem)(struct iwl_priv *priv);
        /* Handling TX */
        void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
                                        struct iwl_tx_queue *txq,
 int iwl_set_hw_params(struct iwl_priv *priv);
 int iwl_init_drv(struct iwl_priv *priv);
 void iwl_uninit_drv(struct iwl_priv *priv);
-/* "keep warm" functions */
-int iwl_kw_init(struct iwl_priv *priv);
-int iwl_kw_alloc(struct iwl_priv *priv);
-void iwl_kw_free(struct iwl_priv *priv);
 
 /*****************************************************
 * RX
 
 /**
  * struct iwl_hw_params
  * @max_txq_num: Max # Tx queues supported
+ * @scd_bc_tbls_size: size of scheduler byte count tables
  * @tx/rx_chains_num: Number of TX/RX chains
  * @valid_tx/rx_ant: usable antennas
  * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
  */
 struct iwl_hw_params {
        u16 max_txq_num;
+       u16 scd_bc_tbls_size;
        u8  tx_chains_num;
        u8  rx_chains_num;
        u8  valid_tx_ant;
 struct iwl_priv;
 
 
-/* Structures, enum, and defines specific to the 4965 */
-
-#define IWL_KW_SIZE 0x1000     /*4k */
-
-struct iwl_kw {
-       dma_addr_t dma_addr;
-       void *v_addr;
+struct iwl_dma_ptr {
+       dma_addr_t dma;
+       void *addr;
        size_t size;
 };
 
        struct iwl_rx_queue rxq;
        struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
        unsigned long txq_ctx_active_msk;
-       struct iwl_kw kw;       /* keep warm address */
+       struct iwl_dma_ptr  kw; /* keep warm address */
+       struct iwl_dma_ptr  scd_bc_tbls;
+
        u32 scd_base_addr;      /* scheduler sram base address */
 
        unsigned long status;
        struct ieee80211_vif *vif;
 
        struct iwl_hw_params hw_params;
-       /* driver/uCode shared Tx Byte Counts */
-       void *shared_virt;
-       /* Physical Pointer to Tx Byte Counts */
-       dma_addr_t shared_phys;
+
 
        /* Current association information needed to configure the
         * hardware */
 
        __le16 finished_fr_nam;
 } __attribute__ ((packed));
 
+
+
+#define IWL_TX_DMA_MASK        DMA_BIT_MASK(36)
+
+#define IWL_NUM_OF_TBS         20
+
+static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
+{
+       return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
+}
+/**
+ * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
+ *
+ * This structure contains dma address and length of transmission address
+ *
+ * @lo: low [31:0] portion of the dma address of TX buffer
+ *     every even is unaligned on 16 bit boundary
+ * @hi_n_len 0-3 [35:32] portion of dma
+ *          4-16 length of the tx buffer
+ */
+struct iwl_tfd_tb {
+       __le32 lo;
+       __le16 hi_n_len;
+} __attribute__((packed));
+
+/**
+ * struct iwl_tfd
+ *
+ * Transmit Frame Descriptor (TFD)
+ *
+ * @ __reserved1[3] reserved
+ * @ num_tbs 0-5 number of active tbs
+ *          6-7 padding (not used)
+ * @ tbs[20]   transmit frame buffer descriptors
+ * @ __pad     padding
+ *
+ * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
+ * Both driver and device share these circular buffers, each of which must be
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
+ *
+ * Driver must indicate the physical address of the base of each
+ * circular buffer via the FH_MEM_CBBC_QUEUE registers.
+ *
+ * Each TFD contains pointer/size information for up to 20 data buffers
+ * in host DRAM.  These buffers collectively contain the (one) frame described
+ * by the TFD.  Each buffer must be a single contiguous block of memory within
+ * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
+ * of (4K - 4).  The concatenates all of a TFD's buffers into a single
+ * Tx frame, up to 8 KBytes in size.
+ *
+ * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ *
+ * Bit fields in the control dword (val0):
+ */
+struct iwl_tfd {
+       u8 __reserved1[3];
+       u8 num_tbs;
+       struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
+       __le32 __pad;
+} __attribute__ ((packed));
+
+
+/* Keep Warm Size */
+#define IWL_KW_SIZE 0x1000     /*4k */
+
 #endif /* !__iwl_fh_h__ */
 
        IWL_TX_FIFO_AC3
 };
 
+static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
+                                   struct iwl_dma_ptr *ptr, size_t size)
+{
+       ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
+       if (!ptr->addr)
+               return -ENOMEM;
+       ptr->size = size;
+       return 0;
+}
+
+static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
+                                   struct iwl_dma_ptr *ptr)
+{
+       if (unlikely(!ptr->addr))
+               return;
+
+       pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
+       memset(ptr, 0, sizeof(*ptr));
+}
+
 static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
 {
        struct iwl_tfd_tb *tb = &tfd->tbs[idx];
                else
                        iwl_tx_queue_free(priv, txq_id);
 
-       /* Keep-warm buffer */
-       iwl_kw_free(priv);
+       iwl_free_dma_ptr(priv, &priv->kw);
+
+       iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
 }
 EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
 
        int txq_id, slots_num;
        unsigned long flags;
 
-       iwl_kw_free(priv);
-
        /* Free all tx/cmd queues and keep-warm buffer */
        iwl_hw_txq_ctx_free(priv);
 
+       ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
+                               priv->hw_params.scd_bc_tbls_size);
+       if (ret) {
+               IWL_ERROR("Scheduler BC Table allocation failed\n");
+               goto error_bc_tbls;
+       }
        /* Alloc keep-warm buffer */
-       ret = iwl_kw_alloc(priv);
+       ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
        if (ret) {
                IWL_ERROR("Keep Warm allocation failed\n");
                goto error_kw;
        /* Turn off all Tx DMA fifos */
        priv->cfg->ops->lib->txq_set_sched(priv, 0);
 
+       /* Tell NIC where to find the "keep warm" buffer */
+       iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
        iwl_release_nic_access(priv);
        spin_unlock_irqrestore(&priv->lock, flags);
 
 
-       /* Tell nic where to find the keep-warm buffer */
-       ret = iwl_kw_init(priv);
-       if (ret) {
-               IWL_ERROR("kw_init failed\n");
-               goto error_reset;
-       }
 
        /* Alloc and init all Tx queues, including the command queue (#4) */
        for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
  error:
        iwl_hw_txq_ctx_free(priv);
  error_reset:
-       iwl_kw_free(priv);
+       iwl_free_dma_ptr(priv, &priv->kw);
  error_kw:
+       iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
+ error_bc_tbls:
        return ret;
 }