[openib-general] RE: [PATCH 3 of 3] mad: large RMPP support, Round 2
Sean Hefty
sean.hefty at intel.com
Sat Feb 18 09:40:09 PST 2006
>+static inline void adjust_last_ack(struct ib_mad_send_wr_private *wr)
>+{
>+ struct ib_mad_multipacket_seg *seg;
>+
>+ if (wr->last_ack < 2)
>+ return;
>+ else if (!wr->last_ack_seg)
>+ list_for_each_entry(seg, &wr->multipacket_list, list) {
>+ if (wr->last_ack == seg->num) {
>+ wr->last_ack_seg = seg;
>+ break;
>+ }
>+ }
>+ else
>+ list_for_each_entry(seg, &wr->last_ack_seg->list, list) {
>+ if (wr->last_ack == seg->num) {
>+ wr->last_ack_seg = seg;
>+ break;
>+ }
>+ }
>+}
If we initialize last_ack_seg to the start of the list, can we combine the else
if and else checks together?
>@@ -647,6 +672,7 @@ static void process_rmpp_ack(struct ib_m
>
> if (seg_num > mad_send_wr->last_ack) {
> mad_send_wr->last_ack = seg_num;
>+ adjust_last_ack(mad_send_wr);
If last_ack_seg references a segment that contains the seg_num, can we eliminate
last_ack?
>+static inline int alloc_send_rmpp_segs(struct ib_mad_send_wr_private *send_wr,
>+ int message_size, int hdr_len,
>+ int data_len, u8 rmpp_version,
>+ gfp_t gfp_mask)
>+{
>+ struct ib_mad_multipacket_seg *seg;
>+ struct ib_rmpp_mad *rmpp_mad = send_wr->send_buf.mad;
>+ int seg_size, i = 2;
>+
>+ rmpp_mad->rmpp_hdr.paylen_newwin =
>+ cpu_to_be32(hdr_len - IB_MGMT_RMPP_HDR + data_len);
>+ rmpp_mad->rmpp_hdr.rmpp_version = rmpp_version;
>+ rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;
>+ ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
>+ send_wr->total_length = message_size;
>+ /* allocate RMPP buffers */
>+ message_size -= sizeof(struct ib_mad);
>+ seg_size = sizeof(struct ib_mad) - hdr_len;
>+ while (message_size > 0) {
>+ seg = kmalloc(sizeof(struct ib_mad_multipacket_seg) + seg_size,
>+ gfp_mask);
It would be convenient if the MAD were cleared for the user, so we don't end of
transferring random data, especially at the end of the user data.
>+ if (!seg) {
>+ printk(KERN_ERR "ib_create_send_mad: RMPP mem "
>+ "alloc failed for len %zd, gfp %#x\n",
>+ sizeof(struct ib_mad_multipacket_seg) + seg_size,
>+ gfp_mask);
>+ free_send_multipacket_list(send_wr);
>+ return -ENOMEM;
>+ }
>+ seg->size = seg_size;
Okay, seg_size is the same for all segments belonging to a single MAD. We can
move this it ib_mad_send_buf.
>+ mad_send_wr->last_ack_seg = NULL;
>+ mad_send_wr->seg_num_seg = NULL;
Mad_send_wr is cleared on allocation. Are there better values to initialize
these variables to? The first/second segment?
>+struct ib_mad_multipacket_seg
>+*ib_rmpp_get_multipacket_seg(struct ib_mad_send_wr_private *wr, int seg_num)
>+{
>+ struct ib_mad_multipacket_seg *seg;
>+
>+ if (seg_num == 2) {
>+ wr->seg_num_seg =
>+ container_of(wr->multipacket_list.next,
>+ struct ib_mad_multipacket_seg, list);
>+ return wr->seg_num_seg;
>+ }
>+
>+ /* get first list entry if was not already done */
>+ if (!wr->seg_num_seg)
See previous comment.
>+struct ib_mad_multipacket_seg
>+*ib_mad_get_multipacket_seg(struct ib_mad_send_buf *send_buf, int seg_num)
>+{
>+ struct ib_mad_send_wr_private *wr;
>+
>+ if (seg_num < 2)
>+ return NULL;
>+
>+ wr = container_of(send_buf, struct ib_mad_send_wr_private, send_buf);
>+ return ib_rmpp_get_multipacket_seg(wr, seg_num);
>+}
Treating the first segment special seems somewhat confusing. (Maybe this is a
result of how the MAD/RMPP header is copied down from userspace?)
>+ if (!rmpp_active && length > sizeof(struct ib_mad)) {
>+ ret = -EINVAL;
>+ goto err_ah;
>+ }
>+
> packet->msg = ib_create_send_mad(agent,
> be32_to_cpu(packet->mad.hdr.qpn),
> 0, rmpp_active,
I think that ib_create_send_mad performs the same check.
- Sean
More information about the general
mailing list